package in.muton.edushare.imageProcessor;

import in.muton.edushare.imageProcessor.processingAPI.IProcessingAPIWrapper;
import in.muton.edushare.imageProcessor.processingAPI.JAIWrapper;
import magick.MagickException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edushare.common.exceptions.EduShareRuntimeException;
import com.edushare.common.file.IFileProcessStrategy;
import com.edushare.common.file.ImageProcessingStrategy;
import com.edushare.common.file.image.ImageSpec;
import com.edushare.common.util.StringUtil;
import com.edushare.common.util.UploadUtils;
import com.edushare.common.vo.FileUploadInfo;
import com.edushare.common.vo.interfaces.IFileUploadable;
import com.edushare.common.vo.interfaces.IProcessor;

public class ImageProcessor implements IProcessor{

	private static Log log = LogFactory.getLog(ImageProcessor.class);
	private ImageProcessingStrategy strategy;
//	private IFileUploadable ifileUploadable;
	private FileUploadInfo fuvo;
	private IProcessingAPIWrapper processingApi;
	private float aspectRatio;
	
	public void setProcessingApi(IProcessingAPIWrapper processingApi) {
		this.processingApi = processingApi;
	}

	public IProcessingAPIWrapper getProcessingApi() {
		if(processingApi==null)
			processingApi = new JAIWrapper();
		return processingApi;
	}

	public ImageProcessor(IFileProcessStrategy fileProcessStrategy, FileUploadInfo fuvo){
		if(fileProcessStrategy ==null || fuvo == null)
			throw new IllegalArgumentException("ImageProcessingStrategy and FileUploadVO cant be null");
		if(!StringUtil.isValid(fuvo.getAbsoluteFilePath()))
			throw new EduShareRuntimeException("Absolute Image Path is NULL.");
		if(!(fileProcessStrategy instanceof ImageProcessingStrategy))
			throw new IllegalArgumentException("Can't process, the processing startegy must be of type " +
					"com.edushare.common.file.ImageProcessingStrategy. You passed, "+ fileProcessStrategy.getClass().getName());
//		this.ifileUploadable = ifileUploadable;
		this.strategy = (ImageProcessingStrategy)fileProcessStrategy;
		this.fuvo = fuvo;
		this.processingApi = new JAIWrapper();
	}
	
	public void process() throws MagickException{
		String origFilePath = fuvo.getAbsoluteFilePath();
		log.info("Processing File: " + origFilePath);
//		ImageInfo origInfo = new ImageInfo(origFilePath);
//		MagickImage image = new MagickImage(origInfo);
		processingApi.loadFileFromPath(origFilePath);
		int origWidth = processingApi.getOrigWidth();
		int origHeight = processingApi.getOrigHeight();
		aspectRatio = (float) (1.0*origWidth/origHeight);
		boolean isHorizontalImage = aspectRatio>1?true:false;
		
		for(ImageSpec imgSpec: strategy.getImageVersions()){
			int finalWidth = 0;
			int finalHeight = 0;
			int cropRectangleWidth = 0;
			int cropRectangleHeight = 0;
			int cropX = 0;
			int cropY = 0;
			
			
			//TODO: move this if-else separate methods
			
			if(imgSpec.getResizeMechanism()== ImageSpec.BEST_FIT)
			{
				/** Resize image to fit in given rectangle defined by imageSpec.width x ImageSpec.height */
				if(isHorizontalImage && imgSpec.getWidth()>0){
					finalWidth=imgSpec.getWidth();
					finalHeight = (int)(1.0*finalWidth/aspectRatio);
				}
				else if(!isHorizontalImage && imgSpec.getHeight()>0){
					finalHeight = imgSpec.getHeight();
					finalWidth = (int)(finalHeight*aspectRatio);
				}
			} 
			else if(imgSpec.getResizeMechanism() == ImageSpec.CROP_TO_DIMENSION && (imgSpec.getWidth()>0 || imgSpec.getHeight()>0))
			{
				
				/** resize by smaller dimension then crop to the provided size */
				
				//Create height absolute width of final image, if not already available
				if(imgSpec.getWidth()<=0)
				{
					cropRectangleHeight = imgSpec.getHeight();
					cropRectangleWidth = (int)(finalHeight*aspectRatio);
				}else if(imgSpec.getHeight()<=0){
					cropRectangleWidth = imgSpec.getWidth();
					cropRectangleHeight = (int)(1.0*finalWidth/aspectRatio);
				}else {
					cropRectangleWidth = imgSpec.getWidth();
					cropRectangleHeight = imgSpec.getHeight();
				}
				
				float cropRectAR = (float)1.0*cropRectangleWidth/cropRectangleHeight;
				
				if(cropRectAR > aspectRatio){
					finalWidth = cropRectangleWidth;
					finalHeight = (int)(1.0*finalWidth/aspectRatio);
					
					cropX = 0;
					cropY = (int)(1.0*(finalHeight-cropRectangleHeight)/2);
				}else{
					finalHeight = cropRectangleHeight;
					finalWidth = (int)(finalHeight*aspectRatio);
					
					cropX = (int)(1.0*(finalWidth-cropRectangleWidth)/2);
					cropY = 0;
				}
				/*if(isHorizontalImage){
					finalHeight = cropRectangleHeight;
					cropY = 0;
					finalWidth =  (int)(finalHeight*aspectRatio);
					cropX = (int)(1.0*(finalWidth-cropRectangleWidth)/2);
					if(cropX<0)
						cropX = 0;
				}else{
					finalWidth = cropRectangleWidth;
					cropX = 0;
					finalHeight = (int)(1.0*finalWidth/aspectRatio);
					cropY = (int)(1.0*(finalHeight-cropRectangleHeight)/2);
					if(cropY<0)
						cropY = 0;
				}*/
				
			}
			else if(imgSpec.getResizeMechanism() == ImageSpec.FIXED_HEIGHT && imgSpec.getHeight()>0)
			{
				/** Resize to the given height, calculate width as per aspect ratio */
				finalHeight = imgSpec.getHeight();
				finalWidth = (int)(finalHeight*aspectRatio);
			}
			else if(imgSpec.getResizeMechanism() == ImageSpec.FIXED_WIDTH && imgSpec.getWidth()>0)
			{
				/** Resize to the given width, calculate height as per aspect ratio */
				finalWidth=imgSpec.getWidth();
				finalHeight = (int)(1.0*finalWidth/aspectRatio);
			}
			
			if(finalHeight > 0 && finalWidth > 0){
//				MagickImage newImage = image.scaleImage(finalWidth, finalHeight);
				processingApi.startNewProcessing();
				processingApi.scaleImage(finalWidth, finalHeight);
				if(cropRectangleHeight>0 && cropRectangleWidth>0){
//					Rectangle cropRect = new Rectangle(cropX, cropY, cropRectangleWidth, cropRectangleHeight);
//					newImage = newImage.cropImage(cropRect);
					processingApi.cropImage(cropX, cropY, cropRectangleWidth, cropRectangleHeight);
				}
//				newImage.setFileName(UploadUtils.getImagePath(origFilePath, imgSpec.getSuffix()));
//				newImage.writeImage(origInfo);
				processingApi.saveImage(UploadUtils.getImagePath(origFilePath, imgSpec.getSuffix()));
			}
		}
		
	}
}
